#ifndef _XX_YY_BMOCK_IN_OUT_PTR_ARG_VAL
#define _XX_YY_BMOCK_IN_OUT_PTR_ARG_VAL
#include <boost/lexical_cast.hpp>
#include "bmock_in_out_arg_val.hpp"
#include "bmock_out_ptr_arg_val.hpp"
#include "bmock_raw_mem.hpp"

namespace bmock {
	template<typename T>
	struct in_out_ptr_arg_val : public out_ptr_arg_val<T> {
		in_out_ptr_arg_val(const char *const n,T *const vp)
			:out_ptr_arg_val<T>(n,vp)
		{}
	protected:
		~in_out_ptr_arg_val() {}
		std::string get_in_value(const arg_checker &chk) const {
			if(this->null_supplied()) return NULL_STR;
			return get_T_value(in_out_rm_pair(this->val_ptr_,this->name_,chk).first);
		}
		std::string get_in_value() const {
			return boost::lexical_cast<std::string>(*this->val_ptr_);
		}
		std::string get_out_value(const arg_checker &chk) const {
			if(this->null_supplied()) return NULL_STR;
			return get_T_value(in_out_rm_pair(this->val_ptr_,this->name_,chk).second);
		}
		static std::string get_T_value(const raw_mem &rm) {
			if(rm.is_empty()) return IGNORE_STR;
			return __get_value(rm.get_T_ptr<T>());
		}
		bool validate(const arg_checker &chk,const std::string &v) const {
			if(chk.check_ptr(this->name_,this->null_expected(v),this->null_supplied())) return true;
			if(this->null_expected(v)&&this->null_supplied()) return false;
			if(this->ignore(v)) return false;
			return chk.check_arg(this->name_,v,__get_value(this->val_ptr_));
		}
		void print(std::ostream &os) const {
			raw_mem rm(this->val_ptr_,1);
			in_out_arg_value_expectation exp(rm.get_T_value<T>());
			exp.print(os);
		}
	};

	
	template<typename T> inline
	arg_val *const make_in_out_arg_val(const char *const n,T *vp) {
		return new in_out_ptr_arg_val<T>(n,vp);
	}
	template<typename T> inline
	arg_val *const make_in_out_arg_val(const char *const n,T &vr) {
		return make_in_out_arg_val<T>(n,&vr);
	}
}

#include <boost/preprocessor/stringize.hpp>

#define __BMOCK_USE_IN_OUT(ARG)\
	bmock::make_in_out_arg_val(BOOST_PP_STRINGIZE(ARG),ARG)

#endif
